package com.bidevalution;

import javax.annotation.PreDestroy;

import com.bstek.ureport.console.UReportServlet;
import org.apache.log4j.Logger;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableScheduling;
import com.bidevalution.business.service.BeFunctionDefineService;
import com.bidevalution.support.websocket.WebSocketServer;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Hello world!
 */
@SpringBootApplication(exclude = {JmsAutoConfiguration.class})
@EnableScheduling
@EnableSwagger2
@PropertySource(value = {"classpath:application.properties", "classpath:application-business.properties",
        "classpath:application-dao.properties", "classpath:application-support.properties",
        "file:${spring.profiles.path}/application.properties",}, ignoreResourceNotFound = true)
@ImportResource(locations = {"classpath:dubbo.xml", "${custom.env}"})
@MapperScan(basePackages = {"com.bidevalution.dao.mapper", "com.bidevalution.dao"})
public class ApplicationStartup {
    // extends SpringBootServletInitializer
    private Logger logger = Logger.getLogger(ApplicationStartup.class);

    public static void main(String[] args) throws Exception {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("The application will be exit.s%%%%%%%%%%%%%%");
        }));
        SpringApplication ctx = new SpringApplication(ApplicationStartup.class);
        ctx.run(args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {
            ctx.getBean(BeFunctionDefineService.class).initialize();
            /**
             * 描述：Tomcat加载完ApplicationContext-main和netty文件后： 1. 启动Netty WebSocket服务器； 2.
             * 加载用户数据； 3. 加载用户交流群数据。
             */
            nettyThread = new Thread(webSocketServer);
            System.out.println(webSocketServer + "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@@@");
            logger.info("开启独立线程，启动Netty WebSocket服务器...");
            nettyThread.start();

        };
    }

    /**
     * 进行注册Servlet
     * 配置 UReport2 需要使用到的servlet
     */
    @Bean
    public ServletRegistrationBean buildUReportServlet() {
        /**
         * @param  servlet
         * @param  urlMappings 值为“/ureport/*”的 urlMappings 是一定不能变的，否则系统将无法运行。
         */
        logger.info("*****注册Servlet用于UReport2*****");
        return new ServletRegistrationBean(new UReportServlet(), "/ureport/*");
    }

    @Autowired
    private WebSocketServer webSocketServer;
    private Thread nettyThread;


    /**
     * 描述：Tomcat服务器关闭前需要手动关闭Netty Websocket相关资源，否则会造成内存泄漏。 1. 释放Netty Websocket相关连接；
     * 2. 关闭Netty Websocket服务器线程。（强行关闭，是否有必要？）
     */
    @SuppressWarnings("deprecation")
    @PreDestroy
    public void close() {
        logger.info("正在释放Netty Websocket相关连接...");
        webSocketServer.close();
        logger.info("正在关闭Netty Websocket服务器线程...");
        nettyThread.stop();
        logger.info("系统成功关闭！");
    }
}
